package com.freelance.vn.apps.puzzle.utils;

import java.util.ArrayList;
import java.util.Random;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.preference.PreferenceManager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import com.freelance.vn.apps.puzzle.R;

public class PlayAreaView extends View {
	private PlayAreaProvider mPlayAreaProvider;
	int positionX = 0;
	int positionY = 0;
	int cellWidth = 0;
	int cellHeight = 0;
	int mTouchMode;
	static final int TOUCH_MODE_TAP = 1;
	static final int TOUCH_MODE_DOWN = 2;
	static final int TOUCH_MODE_REST = 3;
	int prevX, prevY, prevR, prevB;
	Rect prevRect;
	private int mTouchSlop;
	private boolean isForceSwap = false;
	int position = 0;
	int numId = 0;
	
	Boolean imagemove = false;
	
	Context mContext;
	Background mBackground;
	Paint mPaint;
	Boolean isRandom = false;
	private Pictures[] pictures = new Pictures[24]; // array that holds the pictures
	
	// Application
	private ArrayList <Integer> picturesPositions;
	Random randomizer;
	
	public PlayAreaView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
		initProperties(context);
	}

	public PlayAreaView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		initProperties(context);
	}

	public PlayAreaView( Context context ) {
		super(context);
		initProperties(context);
	    mBackground.getBackgroundImage( false, getWidth(), getHeight() );
	}
	
	public void initProperties( Context context ) {
		mContext = context;
		mPaint = new Paint();
		mBackground = new Background( context, mPaint, this, pictures );
		mBackground.generateRandomNos();
		
		prevRect = new Rect();
		Bitmap tmp =BitmapFactory.decodeResource(context.getResources(), R.drawable.empty_photo);
		for ( int i = 0; i < 24; i++ ) {
	    	pictures[i] =  new Pictures( tmp, i );
		}
		final ViewConfiguration configuration = ViewConfiguration.get( context );
		mTouchSlop = configuration.getScaledTouchSlop();
		
		getPicturePositions(mBackground.randomNos);
	}
	public void initProperties( Context context,int imageID ) {
		mContext = context;
		mPaint = new Paint();
		mBackground = new Background( context, mPaint, this, pictures );
		mBackground.generateRandomNos();
		
		prevRect = new Rect();
//		Bitmap tmp =BitmapFactory.decodeResource(context.getResources(), R.drawable.empty_photo);
		for ( int i = 0; i < 24; i++ ) {
	    	pictures[i] =  new Pictures(context,i,imageID );
		}
		final ViewConfiguration configuration = ViewConfiguration.get( context );
		mTouchSlop = configuration.getScaledTouchSlop();
		
		getPicturePositions(mBackground.randomNos);
	}
	
	public void getPicturePositions( ArrayList <Integer> picPosList ) {
		picturesPositions = new ArrayList<Integer>();
		randomizer = new Random();
        generateRandomPics();
		for ( int i = 0; i < picturesPositions.size(); i++ )
			picPosList.set(i, picturesPositions.get(i));
	}
	
	public void generateRandomPics() {
        int number = Math.abs( randomizer.nextInt( 23 ) );
        if ( picturesPositions.size() > 0 ) {
        	picturesPositions.clear();
        }
       	
		for ( int i = 0; i < 24; i++ ) {
			 while( isalreadyAdded( number ) == false ) {
				 number = Math.abs( randomizer.nextInt(24) );
			 }
			 picturesPositions.add( number );
		}
	}
	
	public boolean isalreadyAdded( int number ) {
		boolean numberFound = true;
		 
        if ( picturesPositions.size() == 0 ) {
        	return numberFound;
        } else {
        	for ( int i = 0; i < picturesPositions.size(); i++ ) {
        		if ( picturesPositions.get( i ) == number ) {
					numberFound = false;
					break;
        		}
        	}	 
        }
		return numberFound;
	}
	
	@Override
    public boolean onTouchEvent( MotionEvent event ) {
      	positionX = ( int ) event.getX();
        positionY = ( int ) event.getY();
      
        switch ( event.getAction() ) {
        	case MotionEvent.ACTION_DOWN: {
	        	mTouchMode = TOUCH_MODE_DOWN;
	        	
        		if ( checkForValidNumbers( positionX, positionY ) ) {
        			setNumId( positionX, positionY );
        			prevRect.left = pictures[numId].getX();
        			prevRect.top = pictures[numId].getY();
        			prevRect.right = pictures[numId].getRight();
        			prevRect.bottom = pictures[numId].getBottom();
        			prevX = positionX;
        			prevY = positionY;
        			cellWidth = pictures[23].getRight() - pictures[23].getX();
        			cellHeight = pictures[23].getBottom() - pictures[23].getY();		            			
        			imagemove = true;
        		} else {
        			position = 0;
        			imagemove = false;
        		}
        	}
	        break;
            case MotionEvent.ACTION_MOVE: {
            	if ( imagemove == true ) {
            		final int distY = Math.abs( positionY - prevY );
            		final int distX = Math.abs( positionX - prevX );
            		
					if ( distX > mTouchSlop || distY > mTouchSlop ) {
	         			if ( checkIsWithinBounds( positionX, positionY ) ) {
	         				isForceSwap = true;
	            			invalidate();	
	            		} else {
	            			//Swap
	            			pictures[numId].setX( pictures[23].getX() );
		            		pictures[numId].setY( pictures[23].getY() );
		            		pictures[numId].setRight( pictures[23].getRight() );
		            		pictures[numId].setBottom( pictures[23].getBottom() );
		            		
		            		swapPositions( prevRect );
		            		
		            		isForceSwap = false;
		            		invalidate();
		            		
		            		if ( mBackground.isGameFinished() ) {
		            			mBackground.generateRandomNos();
		            			invalidate();
		            		}
		            		if(mPlayAreaProvider!=null){
		            			mPlayAreaProvider.onItemChanged();
		            		}
		            		imagemove = false;
	            		}
					}
            	}
            }
            break;
            case MotionEvent.ACTION_UP: {
            	if( isForceSwap ) {
            		//Swap
        			pictures[numId].setX( pictures[23].getX() );
            		pictures[numId].setY( pictures[23].getY() );
            		pictures[numId].setRight( pictures[23].getRight() );
            		pictures[numId].setBottom( pictures[23].getBottom() );
            		
            		swapPositions( prevRect );
            		
            		isForceSwap = false;
            		
            		if ( mBackground.isGameFinished() ) {
            			mBackground.generateRandomNos();
            			invalidate();
            		}
            		
            		imagemove = false;
            		invalidate();
            		if(mPlayAreaProvider!=null){
            			mPlayAreaProvider.onItemChanged();
            		}
            	}
            }
            break;
        }
        return true;
    }
	
	@Override
	public void onDraw( Canvas canvas ) {
		Bitmap bitmap = mBackground.getBackgroundImage( getIsRandom(), getWidth(), getHeight() );
		setIsRandom(false);
		canvas.drawBitmap( bitmap, 0, 0, mPaint );
		bitmap.recycle();
	}
	
	public boolean checkForValidNumbers( int x, int y ) {
		boolean validMove = false;
		int numberSquareX = pictures[23].getX();
		int numberSquareY = pictures[23].getY();
		cellWidth = pictures[23].getRight() - pictures[23].getX();
		cellHeight = pictures[23].getBottom() - pictures[23].getY();
		
		/* Check for right */
		if ( x > numberSquareX + cellWidth && x < numberSquareX + cellWidth + cellWidth && y > numberSquareY && y < numberSquareY + cellHeight ) {
			position = 1;
			validMove = true;
		}
		/* Check for left */
		else if ( x > numberSquareX - cellWidth && x < numberSquareX  && y > numberSquareY && y < numberSquareY + cellHeight ) {
			position = 2;
			validMove = true;
		}
		/* Check for top */
		else if ( y > numberSquareY - cellHeight && y < numberSquareY && x > numberSquareX && x < numberSquareX + cellWidth ) {
			position = 3;
			validMove = true;
		}
		/* Check for bottom */
		else if ( y > numberSquareY + cellHeight && y < numberSquareY + cellHeight + cellHeight && x > numberSquareX && x < numberSquareX + cellWidth ) {
			position = 4;
			validMove = true;
		}
		return validMove;
	}
	
	public boolean setNumId( int x, int y ) {
		boolean validMove = false;
			for (Pictures picture : pictures) {
		       	if ( x > picture.getX()  && x < picture.getRight()  && y  > picture.getY() && y < picture.getBottom() ) {
		       		numId = picture.getID(); 
		       		validMove = true;
		       		break;
		       	}
			}
		return validMove;  
	}
	
	public boolean checkIsWithinBounds( int x, int y ) {
		boolean isCanMove = false;
		int deltaX;
		int deltaY;
		switch ( position ) {
			case 1:
				if ( ( x - cellWidth ) > pictures[23].getX() && ( x - cellWidth ) < pictures[23].getRight() ) {
				  	deltaX = Math.abs( prevX - positionX );
				  	pictures[numId].setX( pictures[numId].getX() - deltaX );
	          		pictures[numId].setY( pictures[23].getY() );
	          		pictures[numId].setRight( pictures[numId].getX() + cellWidth );
	          		pictures[numId].setBottom( ( pictures[23].getBottom() ) );
	          		prevX = positionX;
	          		isCanMove = true;
	          		return isCanMove;
				} else {
					isCanMove = false;
				}
				break;
			case 2:
				if ( ( x + cellWidth ) > pictures[23].getX() 
						&& ( x + cellWidth ) < ( pictures[23].getRight() ) ) {
					deltaX = Math.abs( prevX - positionX );
					
				  	pictures[numId].setX( pictures[numId].getX() + deltaX );
	          		pictures[numId].setY( pictures[23].getY() );
	          		pictures[numId].setRight( pictures[numId].getX() + cellWidth );
	          		pictures[numId].setBottom( ( pictures[23].getBottom() ) );
	          		
	          		prevX = positionX;
	          		isCanMove = true;
				    return isCanMove;
				} else {
					isCanMove = false;
				}
			  break;
			case 3:
				if ( ( y + cellHeight ) > pictures[23].getY() && ( y + cellHeight ) < pictures[23].getBottom() ) {
					deltaY = Math.abs(prevY-positionY);
        			pictures[numId].setX( pictures[23].getX() );
	          		pictures[numId].setY( pictures[numId].getY() + deltaY );
	          		pictures[numId].setRight( pictures[23].getRight() );
	          		pictures[numId].setBottom( pictures[numId].getY() + cellHeight );
	          		prevY = positionY;
					isCanMove = true;
					return isCanMove;
				} else {
					isCanMove = false;
				}
				break;
			case 4:
				if ( ( y - cellHeight ) > pictures[23].getY() && ( y - cellHeight ) < pictures[23].getBottom() ) {
					deltaY = Math.abs( prevY - positionY );
        			pictures[numId].setX( pictures[23].getX() );
	          		pictures[numId].setY( pictures[numId].getY() - deltaY );
	          		pictures[numId].setRight( pictures[23].getRight() );
	          		pictures[numId].setBottom( pictures[numId].getY() + cellHeight );
	          		prevY = positionY;
					isCanMove = true;
					return isCanMove;
				} else {
					isCanMove = false;
				}
				break;
		}

		return isCanMove;
	}
	
	public void swapPositions( Rect rect ) {
		pictures[23].setX( rect.left );
		pictures[23].setY( rect.top );
		pictures[23].setRight( rect.right );
		pictures[23].setBottom( rect.bottom );
	}
	
	public void updatePicturePositions() {
		int index = 0;
		System.out.println("picture position size is " + mBackground.picturesPos.size());
	    for ( int i = 0; i < 24; i++ ) {
	    	for ( int j = 0; j < 24; j++ ) {
			    	if ( mBackground.picturesPos.get(i).x == pictures[j].getX() &&  mBackground.picturesPos.get(i).y == pictures[j].getY() ) {
			    		setPicturePosition( index, pictures[j].getID() );
			    	}
    	
	    	}
	    	index++;
	    }
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO Auto-generated method stub
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		LogUtil.e("PlayAreaView", "widthMeasureSpec :" +widthMeasureSpec);
		LogUtil.e("PlayAreaView", "heightMeasureSpec :" +heightMeasureSpec);
	}
	
	public void setPicturePosition( int index, int id ) {
		  picturesPositions.set( index, id );
	}
	
	public void savePicturePosition(Context context) {
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
		Editor editor = null;
		editor = prefs.edit();
	}

	/**
	 * @return the isRandom
	 */
	public Boolean getIsRandom() {
		return isRandom;
	}

	/**
	 * @param isRandom the isRandom to set
	 */
	public void setIsRandom(Boolean isRandom) {
		this.isRandom = isRandom;
	}
	
	public void loadData(Context context,int imageId){					
		for ( int i = 0; i < 24; i++ ) {
	    	pictures[i] =  new Pictures(mContext, i ,imageId);
		}

	}
	
	public PlayAreaProvider getmPlayAreaProvider() {
		return mPlayAreaProvider;
	}

	public void setmPlayAreaProvider(PlayAreaProvider mPlayAreaProvider) {
		this.mPlayAreaProvider = mPlayAreaProvider;
	}

	public interface PlayAreaProvider{
		void onItemChanged();
	}
}